#include "render_ref.h"
#include "../tools/layer_interface.h"
#include "qbe/src/layout/layout.hpp"

namespace qbe::utils::TempRender {

RenderRef::RenderRef(qlib::Reference::s_ptr ref, entt::registry& reg, ecs::Query query, int type) : m_ref(ref), render_type(type) {
  options = query.get_resource<vsg::ref_ptr<vsg::Options>>();
  auto& layer_interface = query.get_resource<tools::LayerInterfaceObjcet>();
  if (m_ref == nullptr) {
    auto cell = std::make_shared<qlib::Cell>();
    auto ref = std::make_shared<qlib::Reference>(cell);
    m_ref = ref;
  }
  switchObject = vsg::Switch::create();
  transform = vsg::MatrixTransform::create();
  switchObject->addChild(true, transform);
  is_show_box = false;
  if (render_type == 0) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    int total_num = 0;
    for (auto layer : polys) {
      total_num += layer.second.size();
      if (total_num > 2000) {
        is_show_box = true;
      }
    }
    if (is_show_box == false) {
      std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
      for (auto layer : polys) {
        std::vector<Mesh2D> layer_meshs;
        for (auto p : layer.second) {
          auto mesh = Mesh2D(p->render_poly(), true);
          layer_meshs.push_back(mesh);
        }
        meshs_map.insert({layer.first, layer_meshs});
      }
      qlib::PathPtrArrayMap lines;
      m_ref->cell->get_paths(true, -1, false, qlib::Tag{0, 0}, lines);
      for (auto layer : lines) {
        std::vector<Mesh2D> layer_meshs;
        for (auto p : layer.second) {
          auto mesh = Mesh2D(p->render_poly(), false);
          layer_meshs.push_back(mesh);
        }
        auto iter = meshs_map.find(layer.first);
        if (iter == meshs_map.end()) {
          meshs_map.insert({layer.first, layer_meshs});
        } else {
          iter->second.insert(iter->second.end(), layer_meshs.begin(), layer_meshs.end());
        }
      }
      std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
      for (auto& [tag, in_meshs] : meshs_map) {
        if (in_meshs.size() > 0) {
          Mesh2D result;
          mesh_merge(in_meshs, result);
          merge_meshs_map.insert({tag, result});
        }
      }

      LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                    "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
      for (auto mesh : merge_meshs_map) {
        auto node = LineMeshNode::create(options, mesh.first, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
        auto layer_info_str = layer_interface.getLayerStyleInfoOnNumFunc(mesh.first.layer);
        if (layer_info_str.empty()) {
          node->setLayerType(vsg::vec4(1.0, 0.0, 0.0, 1.0), "B1");
        } else {
          LayerParam my_layer_param;
          getLayerParam(layer_info_str, my_layer_param);
          node->setLayerType(my_layer_param.border_color, layer_info_str[3]);
        }

        transform->addChild(node);
        line_nodes.insert({mesh.first, node});
      }
    } else {
      auto box = ref->bounding_box();
      auto vertices = vsg::vec2Array::create(4);
      (*vertices)[0] = vsg::vec2(box[0].x, box[0].y);
      (*vertices)[1] = vsg::vec2(box[1].x, box[0].y);
      (*vertices)[2] = vsg::vec2(box[1].x, box[1].y);
      (*vertices)[3] = vsg::vec2(box[0].x, box[1].y);
      vertices->properties.dataVariance = vsg::DYNAMIC_DATA;

      auto indexs = vsg::uintArray::create(8);
      (*indexs)[0] = 0;
      (*indexs)[1] = 1;
      (*indexs)[2] = 1;
      (*indexs)[3] = 2;
      (*indexs)[4] = 2;
      (*indexs)[5] = 3;
      (*indexs)[6] = 3;
      (*indexs)[7] = 0;
      vertices->properties.dataVariance = vsg::DYNAMIC_DATA;

      utils::TempRender::Mesh2D mesh(vertices, indexs);
      LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                    "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
      auto node = LineMeshNode::create(options, qlib::Tag{0, 0}, mesh, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
      auto layer_info_str = layer_interface.getLayerStyleInfoOnNumFunc(0);
      if (layer_info_str.empty()) {
        node->setLayerType(vsg::vec4(1.0, 0.0, 0.0, 1.0), "B1");
      } else {
        LayerParam my_layer_param;
        getLayerParam(layer_info_str, my_layer_param);
        node->setLayerType(my_layer_param.border_color, layer_info_str[3]);
      }

      transform->addChild(node);
      line_nodes.insert({qlib::Tag{0, 0}, node});
    }

  } else if (render_type == 1) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false, true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    FillShaderMaterial2D material{Fill_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), 2.0, 15, 5, 0, 45, 1.0, 1.0, 0, 1, 0}, "shaders/cell/old_fill.vert.spv",
                                  "shaders/cell/old_fill.frag.spv"};
    for (auto mesh : merge_meshs_map) {
      auto node = FillMeshNode::create(options, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
      transform->addChild(node);
    }
  } else if (render_type == 2) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false, true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    PointShaderMaterial2D material{Point_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), 1, 20}, "shaders/cell/key_point.vert.spv",
                                   "shaders/cell/key_point.frag.spv"};
    for (auto mesh : merge_meshs_map) {
      auto node = PointMeshNode::create(options, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
      transform->addChild(node);
    }
  }
}

RenderRef::RenderRef(qlib::Reference::s_ptr ref, int type, vsg::ref_ptr<vsg::Options> opt, std::function<std::vector<std::string>(uint32_t)> func)
    : m_ref(ref), render_type(type) {
  options = opt;
  getLayerStyleInfoOnNumFunc = func;
  if (m_ref == nullptr) {
    auto cell = std::make_shared<qlib::Cell>();
    auto ref = std::make_shared<qlib::Reference>(cell);
    m_ref = ref;
  }
  switchObject = vsg::Switch::create();
  transform = vsg::MatrixTransform::create();
  switchObject->addChild(true, transform);
  is_show_box = false;
  if (render_type == 0) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    int total_num = 0;
    for (auto layer : polys) {
      total_num += layer.second.size();
      if (total_num > 100) {
        is_show_box = true;
      }
    }
    if (is_show_box == false) {
      std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
      for (auto layer : polys) {
        std::vector<Mesh2D> layer_meshs;
        for (auto p : layer.second) {
          auto mesh = Mesh2D(p->render_poly(), true);
          layer_meshs.push_back(mesh);
        }
        meshs_map.insert({layer.first, layer_meshs});
      }
      qlib::PathPtrArrayMap lines;
      m_ref->cell->get_paths(true, -1, false, qlib::Tag{0, 0}, lines);
      for (auto layer : lines) {
        std::vector<Mesh2D> layer_meshs;
        for (auto p : layer.second) {
          auto mesh = Mesh2D(p->render_poly(), false);
          layer_meshs.push_back(mesh);
        }
        auto iter = meshs_map.find(layer.first);
        if (iter == meshs_map.end()) {
          meshs_map.insert({layer.first, layer_meshs});
        } else {
          iter->second.insert(iter->second.end(), layer_meshs.begin(), layer_meshs.end());
        }
      }
      std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
      for (auto& [tag, in_meshs] : meshs_map) {
        if (in_meshs.size() > 0) {
          Mesh2D result;
          mesh_merge(in_meshs, result);
          merge_meshs_map.insert({tag, result});
        }
      }

      LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                    "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
      for (auto mesh : merge_meshs_map) {
        auto node = LineMeshNode::create(options, mesh.first, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
        auto layer_info_str = getLayerStyleInfoOnNumFunc(mesh.first.layer);
        if (layer_info_str.empty()) {
          node->setLayerType(vsg::vec4(1.0, 0.0, 0.0, 1.0), "B1");
        } else {
          LayerParam my_layer_param;
          getLayerParam(layer_info_str, my_layer_param);
          node->setLayerType(my_layer_param.border_color, layer_info_str[3]);
        }

        transform->addChild(node);
        line_nodes.insert({mesh.first, node});
      }
    } else {
      auto box = ref->bounding_box();
      auto vertices = vsg::vec2Array::create(4);
      (*vertices)[0] = vsg::vec2(box[0].x, box[0].y);
      (*vertices)[1] = vsg::vec2(box[1].x, box[0].y);
      (*vertices)[2] = vsg::vec2(box[1].x, box[1].y);
      (*vertices)[3] = vsg::vec2(box[0].x, box[1].y);
      vertices->properties.dataVariance = vsg::DYNAMIC_DATA;

      auto indexs = vsg::uintArray::create(8);
      (*indexs)[0] = 0;
      (*indexs)[1] = 1;
      (*indexs)[2] = 1;
      (*indexs)[3] = 2;
      (*indexs)[4] = 2;
      (*indexs)[5] = 3;
      (*indexs)[6] = 3;
      (*indexs)[7] = 0;
      vertices->properties.dataVariance = vsg::DYNAMIC_DATA;

      utils::TempRender::Mesh2D mesh(vertices, indexs);
      LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                    "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
      auto node = LineMeshNode::create(options, qlib::Tag{0, 0}, mesh, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
      auto layer_info_str = getLayerStyleInfoOnNumFunc(0);
      if (layer_info_str.empty()) {
        node->setLayerType(vsg::vec4(1.0, 0.0, 0.0, 1.0), "B1");
      } else {
        LayerParam my_layer_param;
        getLayerParam(layer_info_str, my_layer_param);
        node->setLayerType(my_layer_param.border_color, layer_info_str[3]);
      }

      transform->addChild(node);
      line_nodes.insert({qlib::Tag{0, 0}, node});
    }

  } else if (render_type == 1) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false, true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    FillShaderMaterial2D material{Fill_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), 2.0, 15, 5, 0, 45, 1.0, 1.0, 0, 1, 0}, "shaders/cell/old_fill.vert.spv",
                                  "shaders/cell/old_fill.frag.spv"};
    for (auto mesh : merge_meshs_map) {
      auto node = FillMeshNode::create(options, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
      transform->addChild(node);
    }
  } else if (render_type == 2) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false, true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    PointShaderMaterial2D material{Point_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), 1, 20}, "shaders/cell/key_point.vert.spv",
                                   "shaders/cell/key_point.frag.spv"};
    for (auto mesh : merge_meshs_map) {
      auto node = PointMeshNode::create(options, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
      transform->addChild(node);
    }
  }
}

RenderRef::RenderRef(qlib::Reference::s_ptr ref, int type, vsg::ref_ptr<vsg::Options> opt) : m_ref(ref), render_type(type) {
  options = opt;
  if (m_ref == nullptr) {
    auto cell = std::make_shared<qlib::Cell>();
    auto ref = std::make_shared<qlib::Reference>(cell);
    m_ref = ref;
  }
  switchObject = vsg::Switch::create();
  transform = vsg::MatrixTransform::create();
  switchObject->addChild(true, transform);
  is_show_box = false;
  if (render_type == 0) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, false, -1, false, qlib::Tag{0, 0}, polys);
    int total_num = 0;
    for (auto layer : polys) {
      total_num += layer.second.size();
      if (total_num > 100) {
        is_show_box = true;
      }
    }
    if (is_show_box == false) {
      std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
      for (auto layer : polys) {
        std::vector<Mesh2D> layer_meshs;
        for (auto p : layer.second) {
          auto mesh = Mesh2D(p->render_poly(), true);
          layer_meshs.push_back(mesh);
        }
        meshs_map.insert({layer.first, layer_meshs});
      }
      qlib::PathPtrArrayMap lines;
      m_ref->cell->get_paths(true, -1, false, qlib::Tag{0, 0}, lines);
      for (auto layer : lines) {
        std::vector<Mesh2D> layer_meshs;
        for (auto p : layer.second) {
          auto mesh = Mesh2D(p->render_poly(), false);
          layer_meshs.push_back(mesh);
        }
        auto iter = meshs_map.find(layer.first);
        if (iter == meshs_map.end()) {
          meshs_map.insert({layer.first, layer_meshs});
        } else {
          iter->second.insert(iter->second.end(), layer_meshs.begin(), layer_meshs.end());
        }
      }
      std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
      for (auto& [tag, in_meshs] : meshs_map) {
        if (in_meshs.size() > 0) {
          Mesh2D result;
          mesh_merge(in_meshs, result);
          merge_meshs_map.insert({tag, result});
        }
      }

      LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                    "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
      for (auto mesh : merge_meshs_map) {
        auto node = LineMeshNode::create(options, mesh.first, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
        node->setLayerType(vsg::vec4(1.0, 0.0, 0.0, 1.0), "B1");

        transform->addChild(node);
        line_nodes.insert({mesh.first, node});
      }
    } else {
      auto box = ref->bounding_box();
      auto vertices = vsg::vec2Array::create(4);
      (*vertices)[0] = vsg::vec2(box[0].x, box[0].y);
      (*vertices)[1] = vsg::vec2(box[1].x, box[0].y);
      (*vertices)[2] = vsg::vec2(box[1].x, box[1].y);
      (*vertices)[3] = vsg::vec2(box[0].x, box[1].y);
      vertices->properties.dataVariance = vsg::DYNAMIC_DATA;

      auto indexs = vsg::uintArray::create(8);
      (*indexs)[0] = 0;
      (*indexs)[1] = 1;
      (*indexs)[2] = 1;
      (*indexs)[3] = 2;
      (*indexs)[4] = 2;
      (*indexs)[5] = 3;
      (*indexs)[6] = 3;
      (*indexs)[7] = 0;
      vertices->properties.dataVariance = vsg::DYNAMIC_DATA;

      utils::TempRender::Mesh2D mesh(vertices, indexs);
      LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                    "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
      auto node = LineMeshNode::create(options, qlib::Tag{0, 0}, mesh, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
      node->setLayerType(vsg::vec4(1.0, 0.0, 0.0, 1.0), "B1");

      transform->addChild(node);
      line_nodes.insert({qlib::Tag{0, 0}, node});
    }

  } else if (render_type == 1) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false, true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    FillShaderMaterial2D material{Fill_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), 2.0, 15, 5, 0, 45, 1.0, 1.0, 0, 1, 0}, "shaders/cell/old_fill.vert.spv",
                                  "shaders/cell/old_fill.frag.spv"};
    for (auto mesh : merge_meshs_map) {
      auto node = FillMeshNode::create(options, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
      transform->addChild(node);
    }
  } else if (render_type == 2) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false, true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    PointShaderMaterial2D material{Point_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), 1, 20}, "shaders/cell/key_point.vert.spv",
                                   "shaders/cell/key_point.frag.spv"};
    for (auto mesh : merge_meshs_map) {
      auto node = PointMeshNode::create(options, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
      transform->addChild(node);
    }
  }
}

RenderRef ::~RenderRef() {}

void RenderRef::translate(qlib::Reference::s_ptr ref) {
  vsg::dmat3 ref_mat = ref_get_mat3(ref);
  vsg::dmat4 temp(ref_mat(0, 0), ref_mat(0, 1), double(0), ref_mat(0, 2),  //
                  ref_mat(1, 0), ref_mat(1, 1), double(0), ref_mat(1, 2),  //
                  double(0), double(0), double(1), double(0),              //
                  ref_mat(2, 0), ref_mat(2, 1), ref_mat(2, 2), double(1));
  transform->matrix = temp;
}

void RenderRef::update() {
  if (render_type == 0) {
    qlib::PolygonPtrArrayMap polys;
    m_ref->cell->get_polygons(true, true, -1, false, qlib::Tag{0, 0}, polys);
    std::unordered_map<qlib::Tag, std::vector<Mesh2D>, qlib::Tag::Hash> meshs_map;
    for (auto layer : polys) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), true);
        layer_meshs.push_back(mesh);
      }
      meshs_map.insert({layer.first, layer_meshs});
    }
    qlib::PathPtrArrayMap lines;
    m_ref->cell->get_paths(true, -1, false, qlib::Tag{0, 0}, lines);
    for (auto layer : lines) {
      std::vector<Mesh2D> layer_meshs;
      for (auto p : layer.second) {
        auto mesh = Mesh2D(p->render_poly(), false);
        layer_meshs.push_back(mesh);
      }
      auto iter = meshs_map.find(layer.first);
      if (iter == meshs_map.end()) {
        meshs_map.insert({layer.first, layer_meshs});
      } else {
        iter->second.insert(iter->second.end(), layer_meshs.begin(), layer_meshs.end());
      }
    }
    std::unordered_map<qlib::Tag, Mesh2D, qlib::Tag::Hash> merge_meshs_map;
    for (auto& [tag, in_meshs] : meshs_map) {
      if (in_meshs.size() > 0) {
        Mesh2D result;
        mesh_merge(in_meshs, result);
        merge_meshs_map.insert({tag, result});
      }
    }

    for (auto node : line_nodes) {
      node.second->clear();
    }
    int i = 0;
    for (auto mesh : merge_meshs_map) {
      auto iter = line_nodes.find(mesh.first);
      if (iter != line_nodes.end()) {
        iter->second->mesh = mesh.second;
        iter->second->update();
      } else {
        LineShaderMaterial2D material{Line_Uniform{vsg::vec4(1.0, 0.0, 0.0, 1.0), vsg::vec2(1316.0, 847.0), 100.0, 70.0, true},
                                      "shaders/cell/line.vert.spv", "shaders/cell/line.frag.spv"};
        auto node = LineMeshNode::create(options, mesh.first, mesh.second, material, VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
        transform->addChild(node);
        line_nodes.insert({mesh.first, node});
      }
    }
  }
}

void RenderRef::updateTransform() {
  double scale = m_ref->magnification;
  double rotation = m_ref->rotation;
  qlib::Vec2 translate = m_ref->origin;

  auto matrix = vsg::scale(vsg::vec3(scale, scale, scale)) * vsg::rotate((float)rotation, vsg::vec3(0, 0, 1)) *
                vsg::translate(vsg::vec3(translate.x, translate.y, 0));

  transform->matrix = matrix;
}

}  // namespace qbe::utils::TempRender